#include "ResBitmapFont.h"
#include "D3D9Engine.h"

CResourceBitmapFont::CResourceBitmapFont()
{
	this->m_fileName	= 0;
	this->m_imgWidth	= 0;
	this->m_imgHeight	= 0;
	this->m_cellWidth	= 0;
	this->m_cellHeight	= 0;
	this->m_colorKey	= 0;

	this->m_sourceTexture		= NULL;
	this->m_spriteInterface		= NULL;

	memset(this->m_fontWidthArray, 0, sizeof(this->m_fontWidthArray));
}

CResourceBitmapFont::~CResourceBitmapFont()
{
}

bool CResourceBitmapFont::CreateBitmapFont(const char *_fileName, int _imgWidth, int _imgHeight, int _cellWidth, int _cellHeight, DWORD _colorKey, const char *_fontCSVFile)
{
	this->m_fileName	= (char*) _fileName;
	this->m_imgWidth	= _imgWidth;
	this->m_imgHeight	= _imgHeight;
	this->m_colorKey	= _colorKey;

	if (_fontCSVFile != NULL)
		this->LoadFontCSV(_fontCSVFile);

	else
	{
		this->m_cellWidth	= _cellWidth;
		this->m_cellHeight	= _cellHeight;
	}

	return true;
}

bool CResourceBitmapFont::OnInitResource(ICompHandler *_handler)
{
	HRESULT hres;

	CD3D9Engine* ptr_engine = (CD3D9Engine*) _handler;

	if (ptr_engine != NULL)
	{
		hres = D3DXCreateSprite(ptr_engine->GetDevice(), &this->m_spriteInterface);

		if (FAILED(hres))
			return false;

		this->m_sourceTexture =  ptr_engine->GetResourceFactory()->RegisterTexture(this->m_fileName, &this->m_imgWidth, &this->m_imgHeight, this->m_colorKey);

		return true;
	}

	return false;
}

bool CResourceBitmapFont::OnFreeResource(ICompHandler *_handler)
{
	CD3D9Engine* ptrEngine = (CD3D9Engine*)_handler;
	if(ptrEngine)
	{
		ptrEngine->GetResourceFactory()->UnregisterTexture(this->m_fileName);
		this->m_sourceTexture = NULL;
	}

	SAFE_RELEASE(this->m_spriteInterface);

	return true;
}

bool CResourceBitmapFont::RenderBitmapText(const char *_text, IDirect3DDevice9 *_device, IDirect3DTexture9 **_targetTexture)
{
	if (this->m_sourceTexture != NULL)
	{
		IDirect3DSurface9 *surface		= NULL;
		IDirect3DSurface9 *backbuffer	= NULL;

		RECT srcrect;
		D3DXVECTOR3 pos = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

		std::stringstream strstream;
		D3DCOLOR currentcolor = D3DCOLOR_XRGB(255,255,255);

		strstream.unsetf(std::ios::skipws);
		strstream << _text;

		(*_targetTexture)->GetSurfaceLevel(0, &surface);

		_device->SetRenderTarget(0, surface);

		_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,255,255,255), 1.0f, 0);

		this->m_spriteInterface->Begin(D3DXSPRITE_ALPHABLEND);

		while (!strstream.eof())
		{
			unsigned char curchar;

			strstream >> curchar;

			if (curchar == '\n')
			{
				pos.x = 0.0f;
				pos.y += (float) this->m_cellHeight;

				continue;
			}

			if (curchar == '|')
			{
				strstream >> std::hex >> currentcolor;
				strstream.ignore();

				continue;
			}

			int fontIndex = curchar;
			int charW = (this->m_fontWidthArray[fontIndex] == 0) ? this->m_cellWidth : this->m_fontWidthArray[fontIndex];

			if (fontIndex > 128)
				charW = this->m_cellWidth;

			srcrect.top = (fontIndex / this->m_cellHeight) * this->m_cellHeight;
			srcrect.bottom = srcrect.top + this->m_cellHeight;

			srcrect.left = (fontIndex % this->m_cellWidth) * this->m_cellWidth;
			srcrect.right = srcrect.left + this->m_cellWidth;

			this->m_spriteInterface->Draw(this->m_sourceTexture, &srcrect, NULL, &pos, currentcolor);

			pos.x += (float) charW;
		}

		this->m_spriteInterface->End();

		_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_FORCE_DWORD, &backbuffer);

		_device->SetRenderTarget(0, backbuffer);

		SAFE_RELEASE(surface);
		SAFE_RELEASE(backbuffer);

		return true;
	}

	return false;
}


bool CResourceBitmapFont::LoadFontCSV(const char* _fileName)
{
	FILE* file = fopen(_fileName, "rt");
	if(file)
	{
		char buffer[256];

		for (int x = 0; x < 2; ++x)
			fgets(buffer, 256, file);

		fscanf(file, "Cell Width,%i\n", &this->m_cellWidth);
		fscanf(file, "Cell Height,%i\n", &this->m_cellHeight);

		for (int i = 0; i < 4; ++i)
			fgets(buffer, 256, file);

		memset(this->m_fontWidthArray, 0, sizeof(this->m_fontWidthArray));

		int dummyInt, dummyInt2;
		for(int i=0; i<256; ++i)
		{
			fscanf(file, "Char %i Base Width,%i\n", &dummyInt, &dummyInt2);
			this->m_fontWidthArray[i] = (char)dummyInt2;
		}

		fclose(file);

		return true;
	}
	else
	{
		LogEntry(Helper::StrConcat("Loading font width definition file ('%s') has failed!", _fileName));
	}

	return false;
}